/* 
 * Copyright 2010 Professional Intellectual Development LLC
 * 
 * Licensed under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
*/

package com.professionalintellectualdevelopment.gae.logging.xmpp;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class XMPPLogFilter implements Filter {   
	private static final Logger log = Logger.getLogger(XMPPLogFilter.class.getName());
	
	private XMPPHandler _xmppHandler;
	private String[] _excludeURIs;
	private String[] _onlyAddresses;
	private boolean active = false;
	
	public void init(FilterConfig filterConfig) throws ServletException {
		try {
			String sender = filterConfig.getInitParameter("sender");
			String recipientsList = filterConfig.getInitParameter("recipients");
			String excludeURIsList = filterConfig.getInitParameter("exclude-uris");
			String onlyAddresses = filterConfig.getInitParameter("only-addresses"); 
			String tLevel = filterConfig.getInitParameter("threshold-level");
			String tLatencyMillis = filterConfig.getInitParameter("threshold-latency-millis");
			String tTotalMillis = filterConfig.getInitParameter("threshold-total-millis");
			
			String[] recipients = (recipientsList != null ? recipientsList.split(";") : null);
			_excludeURIs = (excludeURIsList != null ? excludeURIsList.split(";") : null);
			_onlyAddresses = (onlyAddresses != null ? onlyAddresses.split(";") : null);
			
			Level thresholdLevel = null;
			try { 
				if (tLevel != null && tLevel.trim().length() > 0) {
					thresholdLevel = Level.parse(tLevel.trim());
				}
			} catch (IllegalArgumentException ex) {
				log.severe("Initialization parameter threshold-level is invalid. Filtering by level disabled.");
			}	
			
			long thresholdLatencyMillis = 0;
			try {
				if (tLatencyMillis != null) thresholdLatencyMillis = Long.parseLong(tLatencyMillis);
			} catch (NumberFormatException ex) {
				log.severe("Initialization parameter threshold-latency-millis is invalid. Filtering by latency milliseconds disabled.");				
			}
			
			long thresholdTotalMillis = 0;
			try {
				if (tTotalMillis != null) thresholdTotalMillis = Long.parseLong(tTotalMillis);
			} catch (NumberFormatException ex) {
				log.severe("Initialization parameter threshold-total-millis is invalid. Filtering by total cpu milliseconds disabled.");				
			}
			
			if (recipients != null) {
				_xmppHandler = new XMPPHandler(thresholdLevel, thresholdLatencyMillis, thresholdTotalMillis, sender, recipients);
				log.getParent().addHandler(_xmppHandler);
				active = true;
			} else {
				log.warning("No recipients specified for XMPPLogFilter. Logging will not be active.");
			}
		} catch (Exception ex) {
			log.severe("Logging not active. The following error occurred while attempting to initialize XMPPLogFilter: " + ex.toString());
		} 
	}
	
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {	
		HttpServletRequest request = (HttpServletRequest)req;
		boolean logThisRequest = true;
		try {
			if (active) {
				String uri = request.getRequestURI();
				if (_excludeURIs != null) {
					for (String excludeURI : _excludeURIs) {
						if (excludeURI.endsWith("*")) {
							if (uri.startsWith(excludeURI.substring(0, excludeURI.length()-1))) {
								logThisRequest = false;
								break;
							}
						} else {
							if (uri.equals(excludeURI)) {
								logThisRequest = false;
								break;
							}
						}
					}
				}
				if (logThisRequest) {
					String remoteAddress = request.getRemoteAddr();
					if (_onlyAddresses != null) {
						logThisRequest = false;
						for (String onlyAddress : _onlyAddresses) {
							if (onlyAddress.endsWith("*")) {
								if (remoteAddress.startsWith(onlyAddress.substring(0, onlyAddress.length()-1))) {
									logThisRequest = true;
									break;
								}
							} else {
								if (remoteAddress.equals(onlyAddress)) {
									logThisRequest = true;
									break;
								}
							}
						}
					}
					if (logThisRequest) {
						String method = request.getMethod();
						String userAgent = request.getHeader("user-agent");
						String queryString = request.getQueryString();
						String url = request.getRequestURL().toString();
						_xmppHandler.begin(uri, url, queryString, remoteAddress, method, userAgent);
					}
				}
			}
			filterChain.doFilter(req, resp);
		} finally {
			if (active && logThisRequest) {
				_xmppHandler.end();
			}		
		}
	}     

	public void destroy() {
	}
}

